//
// Created by 陈学明 on 2023/5/19.
//

#ifndef STDSRENDERANDROIDDEMO_STDSEGLCONTEXT_H
#define STDSRENDERANDROIDDEMO_STDSEGLCONTEXT_H
#include <EGL/egl.h>
#include <EGL/eglext.h>

class STDSEGLContext {
public:
    STDSEGLContext() {

    }
    ~STDSEGLContext() {

    }

    void Init() {
        CreateGlesEnv();
    }

    int CreateGlesEnv() {
        const EGLint confAttr[] = {
                EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR,
                EGL_SURFACE_TYPE,EGL_PBUFFER_BIT,
                EGL_RED_SIZE,   8,
                EGL_GREEN_SIZE, 8,
                EGL_BLUE_SIZE,  8,
                EGL_ALPHA_SIZE, 8,
                EGL_DEPTH_SIZE, 16,
                EGL_STENCIL_SIZE,8,
                EGL_NONE
        };

        // EGL context attributes
        const EGLint ctxAttr[] = {
                EGL_CONTEXT_CLIENT_VERSION, 2,
                EGL_NONE
        };

        // surface attributes
        // the surface size is set to the input frame size
        const EGLint surfaceAttr[] = {
                EGL_WIDTH, 1,
                EGL_HEIGHT,1,
                EGL_NONE
        };
        EGLint eglMajVers, eglMinVers;
        EGLint numConfigs;

        int resultCode = 0;
        do {
            //1. 获取 EGLDisplay 对象，建立与本地窗口系统的连接
            m_eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
            if(m_eglDisplay == EGL_NO_DISPLAY) {
                //Unable to open connection to local windowing system
                resultCode = -1;
                break;
            }

            //2. 初始化 EGL 方法
            if(!eglInitialize(m_eglDisplay, &eglMajVers, &eglMinVers)) {
                // Unable to initialize EGL. Handle and recover
                resultCode = -1;
                break;
            }


            //3. 获取 EGLConfig 对象，确定渲染表面的配置信息
            if(!eglChooseConfig(m_eglDisplay, confAttr, &m_eglConf, 1, &numConfigs)) {
                resultCode = -1;
                break;
            }

            //4. 创建渲染表面 EGLSurface, 使用 eglCreatePbufferSurface 创建屏幕外渲染区域
            m_eglSurface = eglCreatePbufferSurface(m_eglDisplay, m_eglConf, surfaceAttr);
            if(m_eglSurface == EGL_NO_SURFACE) {
                switch(eglGetError())
                {
                    case EGL_BAD_ALLOC:
                        // Not enough resources available. Handle and recover
                        break;
                    case EGL_BAD_CONFIG:
                        // Verify that provided EGLConfig is valid
                        break;
                    case EGL_BAD_PARAMETER:
                        // Verify that the EGL_WIDTH and EGL_HEIGHT are
                        // non-negative values
                        break;
                    case EGL_BAD_MATCH:
                        // Check window and EGLConfig attributes to determine
                        // compatibility and pbuffer-texture parameters
                        break;
                }
            }

            //5. 创建渲染上下文 EGLContext
            m_eglCtx = eglCreateContext(m_eglDisplay, m_eglConf, EGL_NO_CONTEXT, ctxAttr);
            if(m_eglCtx == EGL_NO_CONTEXT) {
                EGLint error = eglGetError();
                if(error == EGL_BAD_CONFIG) {
                    // Handle error and recover
                    resultCode = -1;
                    break;
                }
            }

            //6. 绑定上下文
            if(!eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglCtx)) {
                resultCode = -1;
                break;
            }
        } while (false);

        if (resultCode != 0) {

        }
        return resultCode;
    }


    void DestroyGlesEnv() {
        if (m_eglDisplay != EGL_NO_DISPLAY) {
            eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
            eglDestroyContext(m_eglDisplay, m_eglCtx);
            eglDestroySurface(m_eglDisplay, m_eglSurface);
            eglReleaseThread();
            eglTerminate(m_eglDisplay);
        }

        m_eglDisplay = EGL_NO_DISPLAY;
        m_eglSurface = EGL_NO_SURFACE;
        m_eglCtx = EGL_NO_CONTEXT;
    }

    void UnInit() {
        if (m_IsGLContextReady) {
            DestroyGlesEnv();
            m_IsGLContextReady = false;
        }
    }

private:
    EGLConfig  m_eglConf;
    EGLSurface m_eglSurface;
    EGLContext m_eglCtx;
    EGLDisplay m_eglDisplay;
    bool       m_IsGLContextReady;
};

#endif //STDSRENDERANDROIDDEMO_STDSEGLCONTEXT_H
